home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
GL
/
curve
/
curve.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
530 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* curve.c
*
* This is the main file for the Curve Demo.
*
* This program gives a demonstration of the use of the GL
* graphics library to create different types of curves in both
* two and three dimensions. The user may select among different
* types of splines to approximate the curve, view the the control
* points that define the curve, manipulate the control points to see
* the effect on the resulting curve, as well as a host of other
* "whiz-bangs" including setting the curve in motion, viewing the
* curve in 3D perspective, and more.
*
* OPERATION
* Type
* curve <ENTER>
* to begin the demo. To quit, select quit from the menu, or press the
* ESC key.
*
* LEFT MOUSE
* adds a control point in both 2D and 3D modes. Control points are
* given a random z value, which is apparent in 3D mode. If the left
* mouse button is held while adding a point, that point may be moved
* around. Otherwise, control points may be moved after they are added
* using the...
*
* MIDDLE MOUSE
* In 2D mode, the middle allows a control point to be moved by
* pointing at it, pressing and holding the middle button, then
* dragging the control point to a new location.
* In 3D mode, the middle mouse allows manipulation of the view
* volume. When the middle mouse is pressed and dragged within the
* volume, the volume is rotated trackball style around the world x
* and y axes. When the middle mouse is pressed and dragged outside
* the view volume, the volume is rotated about the z axis.
*
* RIGHT MOUSE
* brings up the menus. Menus are fairly self explanatory. The Options
* menu allows the user to add all kinds of whizzy things to the
* display. For some real fun, put the program in 3D mode, then turn
* markers off, smear on, then motion on. Toss in a handful of control
* points (with the left mouse button), then sit back and enjoy.
* The truly daring may manipulate the view volume (with the middle
* mouse) while all this is hapening.
*
* BACKSPACE Key
* deletes the control point nearest to the cursor in both 2D and 3D
* modes.
*
* Written by Howard Look for Silicon Graphics, Inc.
* Based upon the initial program written by Rocky Rhodes and Herb Kuta
* Plenty of help from Thant Tessman^, Gavin Bell and Keith Seto
*
* ^Twinkies for convex hulls and tons of help
*
* June, 1989
*
*/
#include <stdio.h>
#include <gl.h>
#include <device.h>
#include <math.h>
#include <fmclient.h>
#include "event.h"
#include "curve.h"
#include "spaced.h"
/* Prototypes */
void init_window(char *argv[]);
void init_events(void);
void redraw(void);
void process_left_down(void);
void process_left_up(void);
void process_middle_down(void);
void process_middle_up(void);
void process_mouse_motion(void);
void draw_instructions(Boolean);
void quit(void);
void init_fonts(void);
void help(void);
void end_help(void);
Boolean helping(void);
extern void init_menus(void);
extern void init_basis(void);
extern void init_linestyles(void);
extern void add_control_point(void);
extern void delete_control_point(int);
extern void move_control_point(int);
extern void draw_display(void);
extern void clear_window(void);
extern Boolean hit_control_point(int *);
/* Environment variables */
int curve_basis,
display_mode,
curve_precision,
speed,
line_style,
whizbang;
Boolean markers,
hulls,
motion,
smear,
rotating;
extern Boolean moving;
/* type of hardware we are running on */
int hardware;
/* Is drawing active ? */
Boolean draw_active;
/* Lower left corner of the window */
int origin_x, origin_y;
/* Size of the window */
int size_x, size_y;
/* Window's aspect ratio, x/y */
float aspect;
extern Coord geometry[MAX_MARKERS][3];
extern int nailed_marker;
extern Matrix everything_matrix;
void main(int argc, char *argv[])
{
/* Don't hog the graphics unless necessary */
draw_active = FALSE;
/* initialize everything */
init_window(argv);
init_fonts();
draw_instructions(TRUE);
init_basis();
init_linestyles();
init_menus();
init_events();
help();
/* event() looks for the events (as in init_events) and passes
them on to the appropriate routines */
while(TRUE)
event();
}
/*
* Opens the window and sets up the graphic mode.
*/
void init_window(char *argv[])
{
char *t, *strrchr();
if (getgdesc(GD_BITS_NORM_ZBUFFER) == 0)
{
system("inform 'Your system must have a z-buffer to run curve'");
exit(1);
}
keepaspect(1,1);
/* open the window with its invocation as the title (less the path) */
winopen((t=strrchr(argv[0], '/')) != NULL ? t+1 : argv[0]);
/*
* Assume that if we have fewer than 4 RGB bitplanes, may as
* well run in colorindex mode.
*/
if (getgdesc(GD_BITS_NORM_DBL_RED) < 4)
hardware = ECLIPSE8;
else if (getgdesc(GD_BITS_NORM_DBL_RED) >= 8)
hardware = ECLIPSE24;
else
hardware = GT;
doublebuffer();
if (hardware != ECLIPSE8)
RGBmode();
zbuffer(TRUE);
gconfig();
glcompat(GLC_ZRANGEMAP, 0);
getorigin(&origin_x, &origin_y);
getsize(&size_x, &size_y);
aspect = (float)size_x/(float)size_y;
}
/*
* Tells event manager what to pay attention to.
*/
void init_events(void)
{
/* ESC key and WINQUIT quit the program */
add_event(ANY, ESCKEY, UP, quit, 0);
qdevice(ESCKEY);
add_event(ANY, WINQUIT, ANY, quit, 0);
qdevice(WINQUIT);
/* window redraw events */
add_event(ANY, REDRAW, ANY, redraw, 0);
qdevice(REDRAW);
add_event(ANY, LEFTMOUSE, DOWN, process_left_down, NULL);
add_event(ANY, LEFTMOUSE, UP, process_left_up, NULL);
qdevice(LEFTMOUSE);
add_event(ANY, MIDDLEMOUSE, DOWN, process_middle_down, NULL);
add_event(ANY, MIDDLEMOUSE, UP, process_middle_up, NULL);
qdevice(MIDDLEMOUSE);
add_event(ANY, MOUSEX, ANY, process_mouse_motion, NULL);
add_event(ANY, MOUSEY, ANY, process_mouse_motion, NULL);
/* Backspace deletes the nearest control marker */
add_event(ANY, BACKSPACEKEY, DOWN, delete_control_point, NULL);
qdevice(BACKSPACEKEY);
/* Draw the curve whenever the user does not request anything */
/* i.e., there are no events happening */
add_update(&draw_active, draw_display, NULL);
}
/*
* Called by the event manager whenever a redraw event occurs,
* e.g. when the window is resized.
*/
void redraw(void)
{
getorigin(&origin_x, &origin_y);
getsize(&size_x, &size_y);
aspect = (float)size_x/(float)size_y;
viewport(0, size_x-1, 0, size_y-1);
if (helping())
help();
else
draw_display();
}
void process_left_down(void)
{
int marker;
end_help();
if (hit_control_point(&marker))
move_control_point(marker);
else
add_control_point();
}
void process_left_up(void)
{
unqdevice(MOUSEX);
unqdevice(MOUSEY);
moving = FALSE;
end_spaced();
draw_display();
}
void process_middle_down(void)
{
int marker;
end_help();
if (display_mode == TWO_D)
{
if (hit_control_point(&marker))
move_control_point(marker);
}
else
rotate_view_volume();
}
void process_middle_up(void)
{
unqdevice(MOUSEX);
unqdevice(MOUSEY);
rotating = FALSE;
moving = FALSE;
}
/* limits of the view volume */
Coord box_limit[3][2] =
{ { -1.0, 1.0},
{ -1.0, 1.0},
{ -1.0, 1.0}
};
void process_mouse_motion(void)
{
if (rotating && getbutton(MIDDLEMOUSE))
{
update_rotation();
draw_display();
}
else if (moving && (getbutton(LEFTMOUSE)||getbutton(MIDDLEMOUSE)))
{
if (display_mode == TWO_D)
track_motion();
else
spaced(everything_matrix, geometry[nailed_marker], box_limit);
draw_display();
}
}
/*
* Outta here.
*/
void quit(void)
{
gexit();
exit(0);
}
/*
* Routines for writing the intro messages to the screen.
*/
double min(double x, double y)
{
if (x < y)
return x;
else
return y;
}
static fmfonthandle base_font, scaled_font;
void init_fonts(void)
{
fminit();
base_font = fmfindfont("Times-Roman");
}
void setup_string(char str[100], int size, Coord *half)
{
double h_size, v_size, f_size;
Coord length;
h_size = (double)size_x/(double)size;
v_size = (double)size_y/(double)size;
f_size = min(h_size, v_size);
scaled_font = fmscalefont(base_font, f_size);
fmsetfont(scaled_font);
length = fmgetstrwidth(scaled_font, str);
*half = (Coord)(length/size_x);
}
static int looking_at_help;
static int active_state;
void help(void)
{
if (!looking_at_help)
{
looking_at_help = TRUE;
active_state = draw_active;
draw_active = FALSE;
}
draw_instructions(FALSE);
}
void end_help(void)
{
if (looking_at_help)
{
looking_at_help = FALSE;
draw_active = active_state;
}
}
Boolean helping(void)
{
return looking_at_help;
}
void draw_instructions(Boolean initializing)
{
Coord half;
char str[100];
ortho2(-1.0, 1.0, -1.0, 1.0);
czclear(0,getgdesc(GD_ZMAX));
depthcue(FALSE);
sprintf(str,"Curve");
setup_string(str,20,&half);
cmov2(0.0 - half, 0.7);
if (hardware == ECLIPSE8)
color(GREEN);
else
cpack(0xFF00);
fmprstr(str);
sprintf(str,"Interactive Cubic Curve Demonstration");
setup_string(str,40,&half);
cmov2(0.0 - half, 0.6);
if (hardware == ECLIPSE8)
color(GREEN);
else
cpack(0xFF00);
fmprstr(str);
sprintf(str,"Press the left mouse button to add a new control point,");
setup_string(str,50,&half);
cmov2(0.0 - half, 0.3);
if (hardware == ECLIPSE8)
color(WHITE);
else
cpack(0xFFFFFF);
fmprstr(str);
sprintf(str,"or to move an existing control point.");
setup_string(str,50,&half);
cmov2(0.0 - half, .24);
fmprstr(str);
sprintf(str,"In 3D mode, use the middle mouse button");
setup_string(str,50,&half);
cmov2(0.0 - half, .14);
fmprstr(str);
sprintf(str,"to rotate the view volume.");
setup_string(str,50,&half);
cmov2(0.0 - half, .08);
fmprstr(str);
sprintf(str,"Press the right mouse button to bring up a pop-up menu.");
setup_string(str,50,&half);
cmov2(0.0 - half, -.02);
fmprstr(str);
sprintf(str,"Choose \"Display Mode\" to switch from 2D to 3D.");
setup_string(str,50,&half);
cmov2(0.0 - half, -.08);
fmprstr(str);
sprintf(str,"For some interesting shapes, choose a \"Whizbang\" from the");
setup_string(str,50,&half);
cmov2(0.0 - half, -.18);
fmprstr(str);
sprintf(str,"Options menu.");
setup_string(str,50,&half);
cmov2(0.0 - half, -.24);
fmprstr(str);
sprintf(str,"For more information, please see the man page.");
setup_string(str,50,&half);
cmov2(0.0 - half, -.34);
fmprstr(str);
if (initializing)
{
sprintf(str,"Initializing. Please Wait...");
setup_string(str,40,&half);
cmov2(0.0 - half, -.70);
if (hardware == ECLIPSE8)
color(RED);
else
cpack(0xFF);
fmprstr(str);
}
swapbuffers();
}